package com.nineclock.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.model.PutObjectResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nineclock.common.constant.NcConstant;
import com.nineclock.common.constant.SMSConstant;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.oss.OssProperties;
import com.nineclock.common.threadlocal.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.common.utils.UUIDUtils;
import com.nineclock.message.enums.MessageTypeEnum;
import com.nineclock.message.pojo.NcMessage;
import com.nineclock.system.dto.*;
import com.nineclock.system.mapper.*;
import com.nineclock.system.pojo.*;
import com.nineclock.system.service.SysCompanyService;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @author 黑马程序员
 * @Company http://www.ithiema.com
 * @Version 1.0
 */
@Service
@Slf4j
public class SysCompanyServiceImpl implements SysCompanyService {

    @Autowired
    SysCompanyMapper companyMapper;

    //查询当前的企业信息
    @Override
    public SysCompanyDTO queryCompanyInfo() {
        //从线程中获取 企业id
        Long companyId = CurrentUserHolder.get().getCompanyId();
        //根据企业id获取企业信息
        SysCompany company = companyMapper.selectById(companyId);
        if(company == null){
            throw new NcException(ResponseEnum.COMPANY_NOT_FOUND);
        }

        //把pojo 转换为 dto对象
        SysCompanyDTO companyDTO = BeanHelper.copyProperties(company, SysCompanyDTO.class);

        return companyDTO;
    }

    //阿里云 文件存储的 客户端对象
    @Autowired
    OSS oss;

    @Autowired
    OssProperties ossProperties;

    @Override
    public String uploadOss(MultipartFile file) throws IOException {
        //1. 健壮性判断
        if(file == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        //2. 文件大小
        if (file.getSize() > NcConstant.maxFileSize){
            throw new NcException(ResponseEnum.FILE_SIZE_EXCEED_MAX_LIMIT);
        }

        //3. 文件类型
        //获取文件的类型
        String contentType = file.getContentType();
        if( !(contentType != null && NcConstant.ALLOWED_IMG_TYPES.contains(contentType))){
            throw new NcException(ResponseEnum.INVALID_FILE_TYPE);
        }

        //4. 生成唯一的文件名称
        //uuid
        String uuid = UUIDUtils.getUUID();
        //获取文件的后缀
        String name = file.getOriginalFilename(); //获取原始文件名
        //从最后一个 点 开始截取 ， 获取后缀
        String extendsName = name.substring(name.lastIndexOf("."));
        //上传到 oss上的 文件名
        String key  = uuid + extendsName;
        log.info("key: "+key);

        //5.上传文件
        PutObjectResult putObjectResult = oss.putObject(ossProperties.getBucketName(), key, file.getInputStream());

        log.info(putObjectResult.toString());

        //返回值（图片的url）
        //host = https://%s.oss-cn-beijing.aliyuncs.com/asdsfkjasdfasdklfasd.jpg
        String imgPath = String.format(ossProperties.getHost(), ossProperties.getBucketName()) + key;
        log.info("imgPath:" + imgPath);
        return imgPath;
    }

    @Override
    public void updateCompanyInfo(SysCompanyDTO sysCompanyDTO) {
        //健壮性判断
        if(sysCompanyDTO == null || sysCompanyDTO.getName() == null || sysCompanyDTO.getLogo() == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        Long companyId = CurrentUserHolder.get().getCompanyId();
        //获取当前企业 的信息
        SysCompany company = companyMapper.selectById(companyId);

        //更新企业信息
        if(company == null){
            throw new NcException(ResponseEnum.COMPANY_NOT_FOUND);
        }
        company.setName(sysCompanyDTO.getName());
        company.setLogo(sysCompanyDTO.getLogo());

        //持久化到数据库
        companyMapper.updateById(company);


    }

    @Override
    public SysCompanyUserDTO queryCurrentAdmin() {
        //获取企业
        Long companyId = CurrentUserHolder.get().getCompanyId();
        //获取系统主管理员
        SysCompanyUser companyUser = companyMapper.queryCurrentAdmin(companyId);

        if(companyUser == null){
            throw new NcException(ResponseEnum.COMPANY_ADMIN_NOT_EXISTS);
        }
        return BeanHelper.copyProperties(companyUser, SysCompanyUserDTO.class);
    }

    @Autowired
    SysCompanyUserMapper companyUserMapper;

    @Autowired
    RedisTemplate<String ,String> redisTemplate;

    @Autowired
    SysRoleMapper roleMapper;

    @Autowired
    SysCompanyUserRoleMapper companyUserRoleMapper;

    /***
     *
     * 参数： userId：即将要成为管理员的员工id
     *       code： 验证码
     *
     * 1. 根据userId 获取新管理员的员工信息
     * 2. 校验验证码
     * 3. 获取原来的主管理员
     * 4. 删除原来的主管理员的关系
     * 5. 维护新管理员的关系
     *
     *
     * @param changeMainManagerDTO
     */
    @Override
    public void changeSysAdmin(SysChangeMainManagerDTO changeMainManagerDTO) {
        if(changeMainManagerDTO == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        //获取新管理员的员工信息
        SysCompanyUser companyUser = companyUserMapper.selectById(changeMainManagerDTO.getUserId());
        if(companyUser == null){
            throw new NcException(ResponseEnum.USER_NOT_FOUND);
        }
        //从redis中获取验证码
        String key = SMSConstant.SMS_CHANGE_MANAGER_KEY_PREFIX + companyUser.getMobile();
        //获取redis中验证码
        String realCode = redisTemplate.boundValueOps(key).get();
        //校验验证码
        if(!(realCode != null && realCode.equals(changeMainManagerDTO.getCode()))){
            throw new NcException(ResponseEnum.CODE_IMAGE_ERROR);
        }

        //3. 获取原来的主管理员
        SysCompanyUser currentAdmin = companyMapper.queryCurrentAdmin(CurrentUserHolder.get().getCompanyId());
        //获取系统主管理员的 角色信息
        LambdaQueryWrapper<SysRole> roleQw = new LambdaQueryWrapper<>();
        roleQw.eq(SysRole::getCompanyId, CurrentUserHolder.get().getCompanyId());
        roleQw.eq(SysRole::getRoleName, "ROLE_ADMIN_SYS");
        SysRole role = roleMapper.selectOne(roleQw);
        //4. 删除原来的主管理员的关系
        LambdaQueryWrapper<SysCompanyUserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUserRole::getCompanyId, CurrentUserHolder.get().getCompanyId());
        wrapper.eq(SysCompanyUserRole::getCompanyUserId, currentAdmin.getId());
        wrapper.eq(SysCompanyUserRole::getRoleId, role.getId());

        companyUserRoleMapper.delete(wrapper);


        //5. 维护新管理员的关系
        SysCompanyUserRole companyUserRole = new SysCompanyUserRole();
        companyUserRole.setRoleId(role.getId());
        companyUserRole.setCompanyId(CurrentUserHolder.get().getCompanyId());
        companyUserRole.setCompanyUserId(companyUser.getId());

        companyUserRoleMapper.insert(companyUserRole);

    }

    @Override
    public List<SysCompanyDTO> queryCompanyByName(String keyword) {
        if(keyword == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        LambdaQueryWrapper<SysCompany> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(SysCompany::getName, keyword);

        List<SysCompany> companyList = companyMapper.selectList(wrapper);

        if(CollectionUtil.isNotEmpty(companyList)){
            return BeanHelper.copyWithCollection(companyList, SysCompanyDTO.class);
        }

        return null;
    }

    @Autowired
    SysUserMapper userMapper;


    @Autowired
    RocketMQTemplate mqTemplate;

    /**
     * 1. 健壮性判断
     * 2. 更新用户表的数据
     * 3. 员工表新增数据
     * @param applyJoinCompanyUserDTO
     */
    @Override
    public void applyJoinCompany(SysApplyJoinCompanyUserDTO applyJoinCompanyUserDTO) {
        if(applyJoinCompanyUserDTO == null || applyJoinCompanyUserDTO.getUserName() == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        //更新数据库中的用户表
        SysUser user = userMapper.selectById(applyJoinCompanyUserDTO.getUserId());
        if(user == null){
            throw new NcException(ResponseEnum.USER_NOT_FOUND);
        }

        user.setUsername(applyJoinCompanyUserDTO.getUserName());
        user.setEmail(applyJoinCompanyUserDTO.getEmail());
        user.setUpdateTime(new Date());
        user.setLastLoginCompanyId(applyJoinCompanyUserDTO.getCompanyId());

        userMapper.updateById(user);

        //在员工表 新增员工数据
        SysCompanyUser companyUser = new SysCompanyUser();
        companyUser.setUserId(applyJoinCompanyUserDTO.getUserId());
        companyUser.setCompanyId(applyJoinCompanyUserDTO.getCompanyId());
        companyUser.setCompanyName(applyJoinCompanyUserDTO.getCompanyName());
        companyUser.setPost(applyJoinCompanyUserDTO.getPost());
        companyUser.setEmail(applyJoinCompanyUserDTO.getEmail());
        companyUser.setTimeEntry(new Date());
        companyUser.setRemark(applyJoinCompanyUserDTO.getApplyReason()); //申请理由
        companyUser.setEnable((short)0);
        companyUser.setCreateTime(new Date());
        companyUser.setMobile(applyJoinCompanyUserDTO.getMobile());
        companyUser.setUserName(applyJoinCompanyUserDTO.getUserName());
        companyUser.setImageUrl(applyJoinCompanyUserDTO.getImageUrl());

        //存储到数据库
        companyUserMapper.insert(companyUser);


        // TODO  推送申请消息 给系统管理员
        //获取系统主管理员
        SysCompanyUser currentAdmin = companyMapper.queryCurrentAdmin(applyJoinCompanyUserDTO.getCompanyId());


        NcMessage message = new NcMessage();

        message.setMessageType(MessageTypeEnum.COMPANY_APPLY.getType()); //消息类型： 团队推送
        message.setCreateTime(new Date());
        message.setCompanyId(applyJoinCompanyUserDTO.getCompanyId() + "");
        message.setTitle(MessageTypeEnum.COMPANY_APPLY.getTitle()); //消息标题
        message.setContent(applyJoinCompanyUserDTO.getUserName() + "申请加入企业，请及时审批"); // 提示消息内容

        message.setUseStatus(0);
        message.setAudience(MessageTypeEnum.COMPANY_APPLY.getAudience());
        message.setTargets(Arrays.asList(currentAdmin.getMobile()));  //推送的目标(系统管理员的手机号)
        message.setApproveStatue(0); //审核状态

        //申请人信息
        message.setApplyUserId(user.getId());  //申请人 用户id
        message.setApplyUsername(user.getUsername());

        //审批人信息
        message.setApproveUserId(currentAdmin.getUserId());
        message.setApproveUsername(currentAdmin.getUserName());

        mqTemplate.convertAndSend( "messagePushTopic", message);
    }

    @Override
    public void allowedJoinCompany(SysAllowedJoinCompanyUserDTO sysAllowedJoinCompanyUserDTO) {
        if(sysAllowedJoinCompanyUserDTO == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        //1. 更新数据库的状态
        Long applyUserId = sysAllowedJoinCompanyUserDTO.getApplyUserId();
        //根据userid查询 员工信息
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getUserId, applyUserId);
        //申请人 员工信息
        SysCompanyUser companyUser = companyUserMapper.selectOne(wrapper);
        companyUser.setRemark(sysAllowedJoinCompanyUserDTO.getRemark()); //备注
        companyUser.setEnable((short)(sysAllowedJoinCompanyUserDTO.getApproved() ? 1 : 0));

        companyUserMapper.updateById(companyUser);

        //2. 推送消息
        //2.1 推送 通知用户，已经完成审核
        NcMessage message = new NcMessage();
        message.setMessageType(MessageTypeEnum.COMPANY_APPLY_PASS.getType());
        message.setCreateTime(new Date());
        message.setCompanyId(companyUser.getCompanyId() + "");
        message.setTitle(MessageTypeEnum.COMPANY_APPLY_PASS.getTitle());
        message.setContent(companyUser.getUserName() + " 加入企业请求,申请"+(sysAllowedJoinCompanyUserDTO.getApproved() ? "通过": "未通过")+"!");
        message.setUseStatus(1);
        message.setAudience(MessageTypeEnum.COMPANY_APPLY_PASS.getAudience());
        message.setTargets(Arrays.asList(companyUser.getMobile()));
        message.setApproveStatue(1);
        //申请人信息
        message.setApplyUserId(companyUser.getUserId());
        message.setApplyUsername(companyUser.getUserName());

        //审批人信息
        message.setApproveUsername(CurrentUserHolder.get().getUsername());
        message.setApproveUserId(CurrentUserHolder.get().getId());
        message.setApproveResult(sysAllowedJoinCompanyUserDTO.getRemark());


        mqTemplate.convertAndSend("messagePushTopic", message);
        //2.2 推送， 更新mongo
        mqTemplate.convertAndSend("allowedJoinCompanyTopic", sysAllowedJoinCompanyUserDTO.getNotifyMsgId());

    }

    @Override
    public List<SysCompanyDTO> queryCompanyList(Long userId) {
        if(userId == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        List<SysCompany> companyList =companyMapper.queryCompanyList(userId);
        if(CollectionUtil.isEmpty(companyList)){
            throw new NcException(ResponseEnum.USER_NOT_JOIN_COMPANY);
        }

        return BeanHelper.copyWithCollection(companyList, SysCompanyDTO.class);
    }
}
